/*
 * Creates test for use by server
 */
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
import java.util.ArrayList;

/*
 * Used to create tests as well as verify solutions provided by clients.
 */
public class TestCreator {

	private static final String startingState = "YYYYYYYYYRRRRRRRRRGGGGGGGGGOOOOOOOOOBBBBBBBBBWWWWWWWWW";
	private final static char acceptedCharacters[] = { 'X', 'Y', 'Z', 'F', 'R',
			'U', 'L', 'B', 'D' };
	private static ArrayList<Character> acceptedCharactersList = new ArrayList<Character>();
	private final static String[] rotations = { "X", "X'", "Y", "Y'", "Z", "Z'" };
	private final static String commands[] = { "F", "F'", "R", "R'", "U", "U'",
			"L", "L'", "B", "B'", "D", "D'" };

	private static RubikCube cube;
	private Random r;

	public TestCreator() {
		r = new Random();
		cube = new RubikCube();

		for (char c : acceptedCharacters) {
			acceptedCharactersList.add(c);
		}
	}

	// Creates test by giving the cube 'difficulty' number of turns (not
	// utilized)
	public String CreateTest(int difficulty) {
		cube.reset();

		for (int i = 0; i < difficulty; i++) {
			cube.command(commands[r.nextInt(commands.length)]);
		}
		return cube.print();
	}

	// Not presently utilized
	/*
	 * private ArrayList<String> generateCommands(int numCommands) {
	 * 
	 * r.nextInt(commands.length); return null; }
	 */

	// Reads the first line of a text file as a test case.
	// TODO: add check that input string is a valid test
	public String LoadTestFromFile(String filename) {
		String input = null;
		try {
			BufferedReader br = new BufferedReader(new FileReader(new File(
					filename)));
			input = br.readLine();
		} catch (FileNotFoundException fnfe) {
			System.out.println("File not found");
		} catch (IOException ioe) {
			System.out.println("IO Exception caught: " + ioe);
		}

		return input;
	}

	// Checks that solution given uses only allowable commands and is correct
	public static Boolean VerifySolution(String solution, String test) {
		System.out.println("start...");
		String testState = null;
		ArrayList<String> allowedCommands = null;

		String[] testArray = test.split(" ");
		testState = testArray[0];

		// Ensure cube is starting state
		cube.reset();
		// Generate list for allowed commands
		if (testArray.length == 2) {
			allowedCommands = makeAllowedCommandsList(testArray[1]);
		} else {
			allowedCommands = new ArrayList<String>();
			for (String s : rotations) {
				allowedCommands.add(s);
			}
			for (String s : commands) {
				allowedCommands.add(s);
			}
		}

		// Set to state given by test
		cube.command(testState);
		String[] commands = solution.trim().split(" ");
		// Send each command given by the client if it's allowed
		for (String c : commands) {
			if (!allowedCommands.contains(c)) {
				return false;
			}
			cube.command(c);
		}

		// return true if the cube is in the correct state
		String resultString = cube.print();
		Boolean result = resultString.contentEquals(startingState);
		if (!result){
			System.out.println("content not equal!"
					+ "\n" + test
					+ "\n" + solution
					+ "\n" + resultString);
		}
		System.out.println("end...");
		return result;
	}

	// Parses string in file into list of allowed commands
	private static ArrayList<String> makeAllowedCommandsList(
			String allowedCommands) {
		int size = allowedCommands.length();
		ArrayList<String> list = new ArrayList<String>();

		allowedCommands.replace("\"", " ").trim();
		for (int count = 0; count < size; count++) {
			// char c : allowedCommands.toCharArray()){
			String s = allowedCommands.substring(count, count + 1);
			if (count + 1 < size) {
				if (allowedCommands.charAt(count + 1) == '\'') {
					s = s + '\'';
					count++;
				}
			}
			list.add(s);
		}
		return list;
	}
}
